using System.Collections.Generic;
using System.Linq;
using MySql.Data.MySqlClient;
using ODT.Common.ExtensionMethods;
using ODT.Intellisense.Core;
using ODT.Intellisense.Models;

namespace ODT.Intellisense.Services
{
	internal sealed class IntellisenseDatabaseService : IIntellisenseDatabaseService
	{
		private readonly Dictionary<string, IReadOnlyList<string>> level0Dictionary = new Dictionary<string, IReadOnlyList<string>>();

		private readonly Dictionary<string, IReadOnlyList<string>> userDictionary = new Dictionary<string, IReadOnlyList<string>>();

		private readonly object tableLock = new object();

		public string GetAlias(string word, string connectionString)
		{
			word.ThrowArgumentNullException("word");
			connectionString.ThrowArgumentNullException("connectionString");
			List<string> list = new List<string>();
			lock (tableLock)
			{
				MySqlCommand command = LocalCommand.CreateAliasCommand(connectionString, word);
				ExecuteCommand(command, list);
			}
			return list.DefaultIfEmpty(string.Empty).First();
		}

		public string GetHelpText(string suggestion, string connectionString)
		{
			suggestion.ThrowArgumentNullException("suggestion");
			connectionString.ThrowArgumentNullException("connectionString");
			List<string> list = new List<string>();
			lock (tableLock)
			{
				MySqlCommand command = LocalCommand.CreateHelpCommand0(connectionString, suggestion);
				ExecuteCommand(command, list);
				MySqlCommand command2 = LocalCommand.CreateHelpCommand1(connectionString, suggestion);
				ExecuteCommand(command2, list);
				MySqlCommand command3 = LocalCommand.CreateHelpCommand2(connectionString, suggestion);
				ExecuteCommand(command3, list);
			}
			return list.DefaultIfEmpty(string.Empty).First();
		}

		public void GetLevel0List(string connectionString, IList<string> results)
		{
			connectionString.ThrowArgumentNullException("connectionString");
			results.ThrowArgumentNullException("results");
			results.Clear();
			PopulateLevel0Tbl(connectionString, results);
			PopulateUserTbl(connectionString, results);
		}

		public void GetAllOtherLevelList(string[] words, string connectionString, IList<string> results)
		{
			words.ThrowArgumentNullException("words");
			connectionString.ThrowArgumentNullException("connectionString");
			results.ThrowArgumentNullException("results");
			results.Clear();
			switch (words.Length)
			{
			case 1:
				lock (tableLock)
				{
					MySqlCommand command5 = LocalCommand.CreateLevel1Command0(connectionString, words[0]);
					ExecuteCommand(command5, results);
					MySqlCommand command6 = LocalCommand.CreateLevel1Command1(connectionString, words[0]);
					ExecuteCommand(command6, results);
					MySqlCommand command7 = LocalCommand.CreateLevel1Command2(connectionString, words[0]);
					ExecuteCommand(command7, results);
					break;
				}
			case 2:
				lock (tableLock)
				{
					if (words[0].ToLower().Contains("gate") && words[1].ToLower().Contains("chan"))
					{
						MySqlCommand command2 = LocalCommand.CreateLevel2Command0GateChan(connectionString, words[0], words[1]);
						ExecuteCommand(command2, results);
					}
					else
					{
						MySqlCommand command3 = LocalCommand.CreateLevel2Command0(connectionString, words[0], words[1]);
						ExecuteCommand(command3, results);
					}
					MySqlCommand command4 = LocalCommand.CreateLevel2Command1(connectionString, words[0], words[1]);
					ExecuteCommand(command4, results);
					MySqlCommand mySqlCommand = LocalCommand.CreateCommand(connectionString);
					mySqlCommand.CommandText = "Select userlocal.Name from userlocal,userprog where userlocal.ProgId = userprog.ProgId and Match(userprog.ProgID) Against('' In Boolean Mode)";
					ExecuteCommand(mySqlCommand, results);
					break;
				}
			case 3:
				lock (tableLock)
				{
					MySqlCommand command = LocalCommand.CreateLevel3Command0(connectionString, words[0], words[1], words[2]);
					ExecuteCommand(command, results);
					break;
				}
			}
		}

		private void PopulateLevel0Tbl(string connectionString, IList<string> results)
		{
			lock (tableLock)
			{
				if (!level0Dictionary.ContainsKey(connectionString))
				{
					List<string> list = new List<string>();
					MySqlCommand mySqlCommand = LocalCommand.CreateCommand(connectionString);
					mySqlCommand.CommandText = "SELECT software_tbl0.Command FROM software_tbl0 where UserLevel < 4 order by Command";
					ExecuteCommand(mySqlCommand, list);
					mySqlCommand = LocalCommand.CreateCommand(connectionString);
					mySqlCommand.CommandText = "SELECT Name FROM userprog where Type like 'PROG' or Type like 'SUBPROG' or Type like 'PLC' order by Name";
					ExecuteCommand(mySqlCommand, list);
					level0Dictionary[connectionString] = list;
				}
				foreach (string item in level0Dictionary[connectionString])
				{
					results.Add(item);
				}
			}
		}

		private void PopulateUserTbl(string connectionString, IList<string> results)
		{
			lock (tableLock)
			{
				if (!userDictionary.ContainsKey(connectionString))
				{
					List<string> list = new List<string>();
					MySqlCommand mySqlCommand = LocalCommand.CreateCommand(connectionString);
					mySqlCommand.CommandText = "SELECT Name,Type FROM userglobal where Type like 'Ptr' or Type like 'Global' or Type like 'Csglobal' or Type like 'UserDefine'";
					ExecuteCommand(mySqlCommand, list);
					if (list.Count == 0)
					{
						return;
					}
					userDictionary[connectionString] = list;
				}
				foreach (string item in userDictionary[connectionString])
				{
					results.Add(item);
				}
			}
		}

		private void ExecuteCommand(MySqlCommand command, IList<string> results)
		{
			try
			{
				command.Connection.Open();
				MySqlDataReader mySqlDataReader = command.ExecuteReader();
				while (mySqlDataReader.Read())
				{
					results.Add(mySqlDataReader.GetString(0).Trim());
				}
			}
			catch
			{
			}
			finally
			{
				command.Connection.Close();
			}
		}
	}
}
